package com.marcus.tools;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.file.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@SpringBootApplication
@RestController
@RequestMapping("/api")
public class MermaidApplication {
    // 从配置读取的路径
    private Path rootPath;
    private static final String DEFAULT_CONTENT = "graph TD\nA[Start] --> B[End]";

    // 注入配置文件中的路径
    @Value("${mermaid.file-path}")
    private void setRootPath(String filePath) throws IOException {
        this.rootPath = Paths.get(filePath).toAbsolutePath().normalize();
        if (!Files.exists(rootPath)) {
            Files.createDirectories(rootPath);
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(MermaidApplication.class, args);
    }

    /* 文件树接口 */
    @GetMapping("/file/tree")
    public Map<String, Object> getFileTree() {
        return buildTree(rootPath.toFile());
    }

    /* 获取文件内容 */
    @GetMapping("/file/content")
    public ResponseEntity<String> getContent(@RequestParam String path) {
        try {
            Path filePath = validatePath(path);
            return ResponseEntity.ok(readContent(filePath));
        } catch (Exception e) {
            return ResponseEntity.status(500).body(e.getMessage());
        }
    }

    /* 保存文件 */
    @PostMapping("/file/save")
    public ResponseEntity<?> saveFile(@RequestBody Map<String, String> request) {
        try {
            Path filePath = validatePath(request.get("path"));
            Files.write(filePath, request.get("content").getBytes());
            return ResponseEntity.ok().build();
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    /* 创建文件/目录 */
    @PostMapping("/file/create")
    public ResponseEntity<?> createFile(@RequestBody Map<String, String> request) {
        try {
            Path target = validatePath(request.get("path"));
            if (Files.exists(target)) {
                throw new FileAlreadyExistsException("文件已存在");
            }

            if ("file".equals(request.get("type"))) {
                Files.createDirectories(target.getParent());
                Files.write(target, DEFAULT_CONTENT.getBytes());
            } else {
                Files.createDirectories(target);
            }
            return ResponseEntity.ok().build();
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

    // 构建文件树结构
    private Map<String, Object> buildTree(File node) {
        Map<String, Object> tree = new HashMap<>();
        tree.put("name", node.getName());
        tree.put("path", rootPath.relativize(node.toPath()).toString());
        tree.put("type", node.isDirectory() ? "directory" : "file");

        if (node.isDirectory()) {
            File[] children = node.listFiles();
            if (children != null) {
                tree.put("children", Arrays.stream(children)
                        .sorted((a, b) -> {
                            if (a.isDirectory() == b.isDirectory()) return a.getName().compareTo(b.getName());
                            return a.isDirectory() ? -1 : 1;
                        })
                        .map(this::buildTree)
                        .collect(Collectors.toList()));
            }
        }
        return tree;
    }

    // 安全路径验证
    private Path validatePath(String relativePath) throws IOException {
        Path resolvedPath = rootPath.resolve(relativePath).normalize();
        if (!resolvedPath.startsWith(rootPath)) {
            throw new AccessDeniedException("非法路径访问");
        }
        return resolvedPath;
    }

    // 兼容Java8的文件读取
    private String readContent(Path path) throws IOException {
        StringBuilder content = new StringBuilder();
        try (BufferedReader reader = Files.newBufferedReader(path)) {
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line).append("\n");
            }
        }
        return content.toString();
    }
}